package com.miao.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.miao.dto.LoginDto;
import com.miao.dto.UserDto;
import com.miao.cache.TokenCacheHandel;
import com.miao.security.entity.User;
import com.miao.security.entity.UserDetail;
import com.miao.util.JSONUtils;
import com.miao.util.Result;
import com.miao.dao.UserEntityDao;
import com.miao.entity.UserEntity;
import com.miao.service.UserService;
import com.miao.utils.PageData;
import lombok.Data;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.*;

@Service
@Log4j2
public class UserServiceImpl extends ServiceImpl<UserEntityDao, UserEntity> implements UserService {

    /**
     * 编程式事务
     */
    @Autowired
    private TransactionTemplate template;

    @Autowired
    private UserEntityDao dao;

    @Autowired
    private TokenCacheHandel handel;






    public QueryWrapper<UserEntity> getWrapper(Map<String, Object> params) {
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
        return wrapper;
    }

    @Override
    public User GetUserByName(String username) {
        QueryWrapper<UserEntity> wrapper = new QueryWrapper<>();
        wrapper.eq("username", username);
        UserEntity userEntity = dao.selectOne(wrapper);
        return JSONUtils.objParse(userEntity, User.class);
    }

    @Override
    public Result Login(LoginDto dto) {
        User user = GetUserByName(dto.getUsername());
        if (user == null) {
            return new Result<>().error(401, "账号不存在");
        }
        if (verifyPassword(dto.getPassword(), user.getPassword())) {
            String token = UUID.randomUUID().toString().replace("-", "");
            handel.saveUserDefault(token, new UserDetail(user));
            return new Result<>().success(token);
        }
        return new Result<>().error(403, "账号或密码错误");
    }

    @Override
    public Result Register(LoginDto dto) {
        User byName = GetUserByName(dto.getUsername());
        if (byName != null) {
            return new Result<>().error(502, "账号已存在");
        }
        UserEntity userEntity = new UserEntity();
        userEntity.setUsername(dto.getUsername());
        userEntity.setEmail(dto.getEmail());
        userEntity.setPassword(new BCryptPasswordEncoder().encode(dto.getPassword()));
        userEntity.setCreator(0L);
        userEntity.setCreateDate(new Date());
        template.execute(action -> {
            try {
                dao.insert(userEntity);
            } catch (Exception e) {
                action.setRollbackOnly();
                log.error("注册事务异常");
                return new Result<>().error(501);
            }
            String token = UUID.randomUUID().toString().replace(" ", "");
            User user = GetUserByName(dto.getUsername());
            handel.saveUserDefault(token, new UserDetail(user));
            return new Result<>().success(token);
        });
        return new Result<>().error(501);
    }

    @Override
    public Result<Object> Page(Map<String, Object> params) {
        QueryWrapper<UserEntity> wrapper = getWrapper(params);
        int pageSize = Integer.parseInt(params.get("pageSize").toString());
        int currentPage = Integer.parseInt(params.get("currentPage").toString());
        PageDTO<UserEntity> userEntityPageDTO = dao.selectPage(new PageDTO<>(currentPage, pageSize), wrapper);
        List<UserDto> dtos = JSONUtils.listParse(userEntityPageDTO.getRecords(), UserDto.class);
        return new Result<>().success(new PageData<>(dtos, userEntityPageDTO.getTotal()));
    }

    @Override
    public Result<Object> info() {
        Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        return new Result<>().success(principal);
    }

    @Override
    public Result<Object> save(UserDto dto) {
        UserEntity userEntity = new UserEntity();
        log.info(userEntity);
        BeanUtils.copyProperties(dto, userEntity);
        save(userEntity);
        return new Result<>();
    }

    /**
     * 对比密码是否正确
     *
     * @param oldPass 数据库保存密码
     * @param newPass 用户输入密码
     * @return 比对结果
     */
    private boolean verifyPassword(String oldPass, String newPass) {
        return new BCryptPasswordEncoder().matches(oldPass, newPass);
    }
}
